package com.everwin.web.utils;

import org.apache.commons.fileupload.FileItem;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.channels.FileChannel;
import java.security.NoSuchAlgorithmException;

@Component
public class FileStore {

  private final static String algorithm="SHA-256";
  private final static String suffix=".file";
  @Value("${blob.store.location}")
  private String location;

  public FileStore(){}

  public File tarDir(String hash){
    return tarDir(hash,false);
  }

  public File tarDir(String hash, boolean create){
    String lv1=hash.substring(0,1);// 两层
    String lv2=hash.substring(1,4);
    File lv1Dir=new File(location,lv1);
    File lv2Dir=new File(lv1Dir,lv2);
    if(create&&!lv2Dir.exists()) lv2Dir.mkdirs();
    return lv2Dir;
  }

  public File tarFile(String hash){
    return tarFile(hash,false);
  }

  public File tarFile(String fileName, boolean createParent){
    File dir=tarDir(fileName,createParent);
    File file=new File(dir,fileName+suffix);
    return file;
  }

  public String put(FileItem item) throws Exception {
    File tmp=File.createTempFile("mcloud","upload");
    tmp.deleteOnExit();
    item.write(tmp);
    String hash=put(tmp);
    tmp.delete();
    return hash;
  }

  public String put(InputStream is, String file_hash) throws Exception {
    File file=tarFile(file_hash,true);
    if(file.exists()) return file_hash;
    FileOutputStream fos=new FileOutputStream(file);
    int len;
    byte[] buffer=new byte[1024];
    while((len=is.read(buffer))>0)
      fos.write(buffer,0,len);
    fos.close();
    return file_hash;
  }

  public String put(String path) throws NoSuchAlgorithmException, IOException {
    File file=new File(path);
    return put(file);
  }

  public String put(File file) throws NoSuchAlgorithmException, IOException {
    String hash= MogoDigest.digestHex(file,algorithm);
    File target=tarFile(hash,true);
    if(target.exists()) return hash;
    FileOutputStream fos=new FileOutputStream(target);
    FileInputStream fis=new FileInputStream(file);
    FileChannel in=fis.getChannel();
    FileChannel out=fos.getChannel();
    long length=file.length();
    in.transferTo(0,length,out);
    in.close();
    fis.close();
    out.close();
    fos.close();
    return hash;
  }



  public File get(String hash){
    File file=tarFile(hash);
    if(file.exists()) return file;
    else return null;
  }

  public boolean exists(String hash){
    File file=tarFile(hash);
    return file.exists();
  }
}
